Cartograms can be a useful tool to illustrate relative differences across space within a map. Here I combine animate cartograms, using the cartogram and gganimate packages, to show state-level trends over time. To get access to these data, refer to my previous post that includes a link to the data
#necessary libs
library(RSQLite); library(raster); library(tidyverse); library(scales)
library(sf); library(viridis); library(lubridate); library(gifski);
library(cartogram); library(gganimate); library(maptools); library(purrr)
#Read in wildfire data-it's in SQLite format so we'll query the local db
db <- dbConnect(SQLite(), dbname="~/Desktop/fires/data/FPA_FOD_20170508.sqlite")
fires <- dbGetQuery(db, "SELECT * FROM Fires")
#read in shapefile of US states
shape <- shapefile("~/Desktop/fires/data/states_21basic/states.shp")
#set coordinate reference system for later specification
crs = st_crs(4269)After pulling in the fires data and U.S. shapefile, I loop through each year in the data-from 1992 to 2015-and tabulate the number of fires that burned 100 acres or greater by state. Within the loop, I merge this tabulated onto the shapefile and convert it to an sf object so that I can easily manipulate and plot it using ggplot2. Then I bind all years together to produce an data frame/sf object with total fires >100 acres by state from 1992-2015. Finally, I plot the data with animation.
#loop through each year and calculate total fires >100 acres
fire_list <- lapply(unique(fires$FIRE_YEAR), function(yr){
#calculate total fires
fires_temp <- fires %>%
filter(STATE %in% setdiff(STATE, c("HI", "AK")) & FIRE_YEAR==yr) %>%
mutate(fire_big = case_when(
FIRE_SIZE>=100 ~ 1,
FIRE_SIZE<100 ~ 0)
) %>%
group_by(FIRE_YEAR, STATE_ABBR=STATE) %>%
summarise(num_fires=sum(fire_big))
#merge shapefile with fire data
shape_temp <- merge(shape, fires_temp, by="STATE_ABBR", all.x=F)
#convert shape to sf object for ggplot
fires_sf <- st_as_sf(shape_temp, crs=crs)
return(fires_sf)
})
#bind together list of sf objects
fires_all <- reduce(fire_list, sf:::rbind.sf)
#ggaminate wildfires
p <- ggplot(data = fires_all %>%
arrange(FIRE_YEAR)) +
geom_sf(aes(geometry=geometry, fill=num_fires)) +
coord_sf(datum = NA) +
transition_manual(FIRE_YEAR) +
labs(title = 'Total Fires >100 Acres Burned Map-Year:{current_frame}') +
scale_fill_viridis_c(name="Fires", trans="log10")
animate(p, nframes = 100, fps = 2)The result shows an animated progression of wild fire totals across the U.S. over a few decades. Note that I log transform the count of fires to reduce the influence of outliers like Texas and California on the map scale.
Now to actually show a progression of animated cartograms, I run a similar loop across all years but this time I calculate the cartogram and convert back to an sf object. I won’t dive into the underlying mechanics of calculating a cartogram but the product can be helpfully referred to as a value by area map. In which the area of each state, in this case, is proportional to the number of wild fires >100 acres occurring there.
#loop through each year and calculate total fires >100 acres
fire_list <- lapply(unique(fires$FIRE_YEAR), function(yr){
#calculate total fires
fires_temp <- fires %>%
filter(STATE %in% setdiff(STATE, c("HI", "AK")) & FIRE_YEAR==yr) %>%
mutate(fire_big = case_when(
FIRE_SIZE>=100 ~ 1,
FIRE_SIZE<100 ~ 0)
) %>%
group_by(FIRE_YEAR, STATE_ABBR=STATE) %>%
summarise(num_fires=sum(fire_big))
#merge shapefile with fire data
shape_temp <- merge(shape, fires_temp, by="STATE_ABBR", all.x=F)
#calculate cartogram
cart_temp <- cartogram_cont(shape_temp, "num_fires", itermax=7)
#convert shape to sf object for ggplot
fires_sf <- st_as_sf(cart_temp, crs=crs)
return(fires_sf)
})
#bind together list of sf objects
fires_all_cart <- reduce(fire_list, sf:::rbind.sf)
#gganimate cartograms of wildfires
p <- ggplot(data = fires_all_cart %>%
arrange(FIRE_YEAR)) +
geom_sf(aes(geometry=geometry, fill=num_fires)) +
coord_sf(datum = NA) +
transition_manual(FIRE_YEAR) +
labs(title = 'Total Fires >100 Acres Burned Cartogram-Year: {current_frame}') +
scale_fill_viridis_c(name="Fires", trans="log10")
animate(p, nframes = 100, fps = 2)The resulting cartogram animation is similar to the unmanipulated map above through the 1990s. But as we progress toward the 2000s, some states, particularly Texas and the midwest, experience significantly larger number of fires. Watch Texas in particular. We see it peak in 2008, with over 1000 fires in excess of 100 acres burned. Now I’ll show the same maps except I plot number of acres burned for all fires for a given state-year combination. I’ll exclude the code for those since it’s almost similar to what’s above but you can find it on my site’s github repo as well.
The unadulterated map shows a stark east-west pattern, where western states have more acres burned, that remains consistent through time. The northeastern U.S. has had relatively few acres burned which, all things being equal, is to be expected given that northeastern states are relatively smaller. A few periods in the mid 2000s pop up as high burn years in the West but, overall, it’s tough to glean any other time trends.
Using the same data as the previous “Acres Burned” map, this cartogram provides an added dimension. The advantage of this type of map is the ability to further emphasize spatial or temporal trends, or enable the identification of other patterns. One pattern clearly shown is how this visual really highlights the proliferation of more destructive fires in the West around the mid 2000s. Additionally, I could have calculated the cartogram boundaries based off another variable, such as population, to add another dimension to the map that may be related to wild fire intensity. Maybe that will come in future posts.
A work by Will Godwin